#include "net/Pollers/Poller.h"
#include "net/Channel.h"
#include "net/EventLoop.h"
#include "Base/Logger.h"
#include <poll.h>
#include <cassert>

namespace toym
{
namespace net
{

////////////////////////////////////////////////////
//////    Public methods
////////////////////////////////////////////////////
Poller::Poller()
    : m_pfds(),
      channelMap()
{}

Poller::~Poller() = default;

int Poller::poll() {
    return ::poll(m_pfds.data(), m_pfds.size(), IPoller::intervalMicroseconds);
}

void Poller::updateChannel(Channel& channel) {
    assert(channel.getFd() >= 0);
    if (channel.getIdx() < 0) {
        // new channel
        LOG_INFO << "new Channel for fd " << channel.getFd();
        // channelMap中必须没有该chennel
        assert(channelMap.count(channel.getFd()) == 0);

        struct pollfd pfd;
        pfd.fd = channel.getFd();
        pfd.events = channel.getEvents();
        pfd.revents = 0;
        channel.setIdx(m_pfds.size());
        m_pfds.push_back(pfd);
        channelMap[pfd.fd] = &channel;
    } else {
        // update channel
        LOG_INFO << "update Channel for fd " << channel.getFd();
        
        auto idx = channel.getIdx();
        int fd = channel.getFd();
        
        // channelMap中必须有该chennel
        assert(channelMap.count(fd) == 1);

        // channelMap数据确认
        assert(&channel == channelMap[fd]);

        // pollfd 数据确认
        assert(idx > 0);
        assert(static_cast<std::size_t>(idx) < m_pfds.size());
        struct pollfd& pfd = m_pfds[idx];
        assert(pfd.fd == fd || pfd.fd == (~fd));
        pfd.fd = fd;
        pfd.events = channel.getEvents();
    }

    if (channel.isNonEvent()) {
        int newFd = m_pfds[channel.getIdx()].fd;
        newFd = ~newFd;
        m_pfds[channel.getIdx()].fd = newFd;
    }
}

void Poller::removeChannel(Channel& channel) {
    auto idx = channel.getIdx();
    int fd = channel.getFd();
    assert(idx >= 0);
    assert(fd >= 0);
    assert(channelMap.count(fd) == 1);
    channelMap.erase(fd);
    if (static_cast<std::size_t>(idx+1) !=  m_pfds.size()) {
        // 不在vector中的最后一个
        // 移到最后一个
        struct pollfd& lastPfd = m_pfds.back();
        // 确定最后一个pfd是正确的
        int lastFd = lastPfd.fd;
        if (lastFd < 0)
            lastFd = ~lastFd;
        Channel* lastChannel = channelMap[lastFd];
        // 最后一个channel的fd检查
        assert(lastFd == lastChannel->getFd());
        // 最后一个chennel的idx检查
        assert(m_pfds.size() == static_cast<std::size_t>(lastChannel->getIdx() + 1));
        std::swap(m_pfds[idx], lastPfd);
        lastChannel->setIdx(idx);
        channel.setIdx(m_pfds.size() - 1);
    }
    assert(static_cast<std::size_t>(channel.getIdx()+1) == m_pfds.size());
    m_pfds.pop_back();
}

std::vector<Channel*> Poller::getActiveChannels(int nActive) {
    std::vector<Channel*> ret;
    for (auto& pfd: m_pfds) {
        if (nActive <= 0)
            break;
        if (pfd.revents != 0) {
            --nActive;
            int fd = pfd.fd;
            // 不能是没监控的描述符
            assert(fd >= 0);
            assert(channelMap.count(fd) == 1);
            Channel* pc = channelMap[fd];
            pc->setRevnets(pfd.revents);
            ret.push_back(pc);
        }
    }
    return ret;
}

} // namespace net

} // namespace toym
